/*********************************************************************** * Copyright (c) 2007 Anyware Technologies * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Anyware Technologies - initial API and implementation * * $Id: TableObjectManager.java,v 1.1 2008/05/26 12:25:14 jlescot Exp $ **********************************************************************/ package org.eclipse.emf.ecoretools.tabbedproperties.internal.sections; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EEnumLiteral; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecoretools.tabbedproperties.internal.Messages; import org.eclipse.emf.ecoretools.tabbedproperties.sections.widgets.ChooseDialog; import org.eclipse.emf.edit.command.AddCommand; import org.eclipse.emf.edit.command.CommandParameter; import org.eclipse.emf.edit.command.DeleteCommand; import org.eclipse.emf.edit.command.RemoveCommand; import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.provider.ItemPropertyDescriptor; import org.eclipse.emf.edit.ui.celleditor.FeatureEditorDialog; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; /** * Class that manages model changes. This manager supports four basic types such * as boolean, string, int and enumerations. * * Creation 10 august 06 * * @author <a href="alfredo@anyware-tech.com">Jose Alfredo SERRANO</a> */ public class TableObjectManager { /** The object id for the '<em>EBoolean</em>' data type */ public static final int BOOL = 1; /** The object id for the '<em>EENUM</em>' data type */ public static final int ENUM = 2; /** The object id for the '<em>EString</em>' data type */ public static final int STR = 3; /** The object id for the '<em>EInteger</em>' data type */ public static final int INT = 4; /** The object id for the '<em>BIG_Integer</em>' data type */ public static final int B_INT = 6; /** The object id for the '<em>EReference</em>' */ public static final int REF = 5; /** The object id for the '<em>EDouble</em>' */ public static final int DBL = 7; private EObject inputEObject; private EStructuralFeature feature; private EClassifier type; private EditingDomain editingDomain; private ILabelProvider labelProvider; /** * Constructor Creates a new instance of an EObjectManager. * * @param eObject * Object to manage * @param structuralFeature * Structural Feature to edit. Actually this may be a List type */ public TableObjectManager(EObject eObject, EStructuralFeature structuralFeature) { inputEObject = eObject; feature = structuralFeature; type = feature.getEType(); } /** * Add a new task to the collection of elements */ public void addElement() { addElement(createNewElement()); } /** * Add a new element to the collection of elements * * @param newElement * the Element to add */ public void addElement(Object newElement) { if (newElement == null) { return; } Command command; if (newElement instanceof List) { List<?> newElements = (List<?>) newElement; CompoundCommand cpcmd = new CompoundCommand(); for (Object element : newElements) { cpcmd.append(AddCommand.create(editingDomain, inputEObject, feature, element)); } command = cpcmd; } else { command = AddCommand.create(editingDomain, inputEObject, feature, newElement); } editingDomain.getCommandStack().execute(command); } /** * Removes the given element from the feature list * * @param element * Element to remove */ public void removeElement(Object element) { Command removeCmd = RemoveCommand.create(editingDomain, inputEObject, feature, element); editingDomain.getCommandStack().execute(removeCmd); } /** * Updates the Structural Feature setting its value with the given object * * @param newValue * The new element to set. */ public void updateElement(Object newValue) { if (newValue == null) { return; } Command command; List<?> oldValues = (List<?>) inputEObject.eGet(feature); if (newValue instanceof List) { List<?> newElements = (List<?>) newValue; CompoundCommand cpcmd = new CompoundCommand(); // Search for deleted items for (Object element : oldValues) { if (!newElements.contains(element)) { cpcmd.append(RemoveCommand.create(editingDomain, inputEObject, feature, element)); } } // Search for added items for (Object element : newElements) { if (!oldValues.contains(element)) { cpcmd.append(AddCommand.create(editingDomain, inputEObject, feature, element)); } } command = cpcmd; } else { command = AddCommand.create(editingDomain, inputEObject, feature, newValue, oldValues.size()); } editingDomain.getCommandStack().execute(command); } /** * Modifies the value of an element in the list * * @param oldValue * old value in order to get its place * @param newValue * new value to insert that the olds value place */ public void elementChanged(Object oldValue, Object newValue) { if (!oldValue.equals(newValue)) { Command command = null; if (feature.isMany()) { List<?> list = (List<?>) inputEObject.eGet(feature); int index = list.indexOf(oldValue); CompoundCommand cpcmd = new CompoundCommand(); cpcmd.append(DeleteCommand.create(editingDomain, oldValue)); cpcmd.append(AddCommand.create(editingDomain, inputEObject, feature, Collections.singleton(newValue), index)); command = cpcmd; } else { command = SetCommand.create(editingDomain, inputEObject, feature, newValue); } editingDomain.getCommandStack().execute(command); } } /** * This method should be calld if client wants to manage model changements * * @param editingDomain * the editingDomain to set */ public void setEditingDomain(EditingDomain editingDomain) { this.editingDomain = editingDomain; } /** * Set the LabelProvider to use * * @param labelProvider */ public void setLabelProvider(ILabelProvider labelProvider) { this.labelProvider = labelProvider; } /** * @return the feature to edit */ public EStructuralFeature getManagedFeature() { return feature; } /** * @return Returns the input Eobject */ public EObject getInputEObject() { return inputEObject; } /** * Get the Feature type of the EObject feature of the manager This class * manages list. The return type will be certainly a EList/List type * * @return feature type */ public List<?> eGet() { if (feature.isMany()) { return (List<?>) inputEObject.eGet(feature); } return new ArrayList<Object>(1); } /** * TODO Comment this method * * @return String[] */ public String[] getEnumLiterals() { List<EEnumLiteral> literals = ((EEnum) type).getELiterals(); String[] result = new String[literals.size()]; for (int i = 0; i < result.length; i++) { result[i] = literals.get(i).getLiteral(); } return result; } /** * TODO Comment this method * * @param value * @return Object */ public Object createEnum(int value) { String literal = ((EEnum) type).getEEnumLiteral(value).getLiteral(); return EcoreUtil.createFromString((EDataType) type, literal); } /** * Creates a new type of elements * * @return The new element */ private Object createNewElement() { Object newElement = null; switch (getEType()) { case BOOL: // TODO this case may be removed newElement = new Boolean(false); break; case ENUM: // TODO this case may be removed newElement = createEnum(0); break; case INT: newElement = new Integer(0); break; case B_INT: newElement = new BigInteger("0"); //$NON-NLS-1$ break; case DBL: newElement = new Double(0); break; case STR: newElement = Messages.TableObjectManager_NewString; break; case REF: if (((EClass) type).isAbstract()) { newElement = createObjectFromDialog(); } else { newElement = EcoreUtil.create((EClass) type); } break; default: break; } return newElement; } /** * Computes the EStructuralFeature type. When the type is an enumeration * this function will initialize the literals array * * @see EcorePackage#EBOOLEAN , EcorePackage#ESTRING , EcorePackage#EINT or * EcorePackage#EEnum * @see #BOOL * @see #INT * @see #STR * @see #ENUM * * @return An integer code which determine the type */ public int getEType() { if (type instanceof EEnum) { return ENUM; } else if (type instanceof EDataType) { Class<?> clazz = type.getInstanceClass(); if (clazz == int.class || clazz == Integer.class) { return INT; } else if (clazz == double.class || clazz == Double.class) { return DBL; } else if (clazz == BigInteger.class) { return B_INT; } else if (clazz == String.class) { return STR; } else if (clazz == boolean.class || clazz == Boolean.class) { return BOOL; } else { return 0; } } else if (type instanceof EClass) { return REF; } else { return 0; } } /** * Return the new List of elements that have been specified in the * FeatureEditorDialog. * * @return List */ public List<?> chooseObjectsFromDialog() { Collection<EObject> choiceOfValues = ItemPropertyDescriptor.getReachableObjectsOfType(inputEObject, feature.getEType()); Shell shell = Display.getDefault().getActiveShell(); String displayName = Messages.TableObjectManager_ChooseObjectsToAdd; List<?> choices = new ArrayList<EObject>(choiceOfValues); FeatureEditorDialog dialog = new FeatureEditorDialog(shell, labelProvider, inputEObject, feature, displayName, choices); dialog.open(); return dialog.getResult(); } /** * @return Object */ public Object createObjectFromDialog() { Collection<?> descriptors = editingDomain.getNewChildDescriptors(inputEObject, null); Object[] selection = descriptors.toArray(); if (selection.length > 1) { Object[] values = new Object[selection.length]; for (int i = 0; i < selection.length; i++) { values[i] = ((CommandParameter) selection[i]).getEValue(); } Shell shell = Display.getDefault().getActiveShell(); ChooseDialog dialog = new ChooseDialog(shell, values); dialog.setLabelProvider(labelProvider); if (dialog.open() == Window.OK) { selection = dialog.getResult(); } else { selection = new Object[0]; } } if (selection.length > 0) { return selection[0]; } return null; } }